package com.ego.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ego.common.util.PageUtil;
import com.ego.common.vo.PageVo;
import com.ego.product.po.AttrGroupRelation;
import com.ego.product.po.ProductAttrValue;
import com.ego.product.service.AttrGroupRelationService;
import com.ego.product.service.ProductAttrValueService;
import com.ego.product.vo.AttrGroupRelationVo;
import com.ego.product.vo.AttrGroupSearchVo;
import com.ego.product.vo.DetailVo;
import com.ego.product.vo.spu.Attr;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ego.product.dao.AttrGroupDao;
import com.ego.product.po.AttrGroup;
import com.ego.product.service.AttrGroupService;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author KamTang
 * @program: ego
 * @description 属性分组对应实现类
 * @date 2022-11-13 12:56:14
 */
@Service("attrGroupService")
public class AttrGroupServiceImpl extends ServiceImpl<AttrGroupDao, AttrGroup> implements AttrGroupService {

    @Autowired
    private AttrGroupRelationService attrGroupRelationService;
    @Autowired
    private ProductAttrValueService productAttrValueService;

    @Override
    public PageVo<AttrGroup> search(AttrGroupSearchVo search) {
        LambdaQueryWrapper<AttrGroup> query = Wrappers.<AttrGroup>lambdaQuery()
                .eq(StringUtils.isNotEmpty(search.getKeyword()), AttrGroup::getAttrGroupId, search.getKeyword())
                .eq(search.getCategoryId() != 0, AttrGroup::getCategoryId, search.getCategoryId());
        if (StringUtils.isNotEmpty(search.getKeyword())) {
            query.and(q -> q.like(AttrGroup::getAttrGroupName, search.getKeyword()));
        }
        Page<AttrGroup> page = baseMapper.selectPage(Page.of(search.getPageNum(), search.getPageSize()), query);
        return PageUtil.toPage(page);
    }

    @Override
    public void deleteRelations(AttrGroupRelationVo[] vos) {
        List<AttrGroupRelation> entities = Arrays.stream(vos)
                .map(AttrGroupRelation::fromVo).collect(Collectors.toList());
        baseMapper.deleteRelations(entities);
    }

    /**
     * SQL语句
     * SELECT
     * 	pav.spu_id,
     * 	ag.attr_group_name,
     * 	ag.attr_group_id,
     * 	aar.attr_id,
     * 	attr.attr_name,
     * 	pav.attr_value
     * FROM
     * 	`pms_attr_group` ag
     * 	LEFT JOIN `pms_attr_group_relation` aar ON aar.attr_group_id = ag.attr_group_id
     * 	LEFT JOIN `pms_attr` attr ON attr.attr_id = aar.attr_id
     * 	LEFT JOIN `pms_product_attr_value` pav ON pav.attr_id = attr.attr_id
     * WHERE
     * 	ag.category_id = #{categoryId} AND pav.spu_id = #{spuId}
     */
    @Override
    public List<DetailVo.DetailSpuAttrGroupVo> withAttrsBySpuId(Long spuId, Long categoryId) {
        List<DetailVo.DetailSpuAttrGroupVo> spuAttrGroups = new ArrayList<>();
        // 根据categoryId获取当前spu有多个对应的属性分组
        List<AttrGroup> attrGroups = this.baseMapper.selectList(new QueryWrapper<AttrGroup>()
                .eq("category_id", categoryId));
        if (!CollectionUtils.isEmpty(attrGroups)) {
            Map<Long, AttrGroup> attrGroupMap = attrGroups.stream()
                    .collect(Collectors.toMap(AttrGroup::getAttrGroupId, Function.identity(), (e1, e2) -> e2));
            // 分组id
            List<Long> attrGroupIds = attrGroups.stream().map(AttrGroup::getAttrGroupId).collect(Collectors.toList());
            List<AttrGroupRelation> attrGroupRelations = attrGroupRelationService
                    .list(new QueryWrapper<AttrGroupRelation>().in("attr_group_id", attrGroupIds));
            List<Long> attrIds = attrGroupRelations.stream().map(AttrGroupRelation::getAttrId).sorted()
                    .collect(Collectors.toList());
            Map<Long, List<AttrGroupRelation>> attrGroupRelationMap = attrGroupRelations.stream()
                    .collect(Collectors.groupingBy(AttrGroupRelation::getAttrGroupId, Collectors.toList()));

            // 使用attrId去pms_product_attr_value获取具体属性值
            // 经过分析，这里不需要再去pms_attr获取attr信息，就算spu中有些属性没有设置，但是已经使用spu_id过滤了。
            List<ProductAttrValue> productAttrValues = productAttrValueService.list(new QueryWrapper<ProductAttrValue>()
                    .in("attr_id", attrIds)
                    .eq("spu_id", spuId));
            Map<Long, ProductAttrValue> productAttrValueMap = productAttrValues.stream()
                    .collect(Collectors.toMap(ProductAttrValue::getAttrId, Function.identity(), ((e1, e2) -> e2)));

            spuAttrGroups = attrGroupIds.stream().map(attrGroupId -> {
                DetailVo.DetailSpuAttrGroupVo detailSpuAttrGroup = new DetailVo.DetailSpuAttrGroupVo();
                List<Attr> spuBaseAttrs = attrGroupRelationMap.get(attrGroupId).stream().map(attrGroupRelation -> {
                    Attr attr = new Attr();
                    ProductAttrValue productAttrValue = productAttrValueMap.get(attrGroupRelation.getAttrId());
                    attr.build(Optional.ofNullable(productAttrValue).map(ProductAttrValue::getAttrName).orElse(null),
                            Optional.ofNullable(productAttrValue).map(ProductAttrValue::getAttrValue).orElse(null));
                    return attr;
                }).collect(Collectors.toList());
                AttrGroup attrGroup = attrGroupMap.get(attrGroupId);
                detailSpuAttrGroup.build(attrGroup.getAttrGroupName(), spuBaseAttrs);
                return detailSpuAttrGroup;
            }).collect(Collectors.toList());
        }
       return spuAttrGroups;
    }
}
